import { Component, Input } from '@angular/core';
import { NgbModal, ModalDismissReasons, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import * as Collections from 'typescript-collections';

import { ModelInputComponent } from './components';
import { JgongCreatorService } from './services';
import { DeepcopyService } from './services'

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'app';

  jgData: number[][] = [
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    , [10, 11, 12, 13, 14, 15, 16, 17, 18]
    , [19, 20, 21, 22, 23, 24, 25, 26, 27]
    , [28, 29, 30, 31, 32, 33, 34, 35, 36]
    , [37, 38, 39, 40, 41, 42, 43, 44, 45]
    , [46, 47, 48, 49, 50, 51, 52, 53, 54]
    , [55, 56, 57, 58, 59, 60, 61, 62, 63]
    , [64, 65, 66, 67, 68, 69, 70, 71, 72]
    , [73, 74, 75, 76, 77, 78, 79, 80, 81]
  ];

  givenCell: boolean[][] = [
    [false, false, false, false, false, false, false, false, false]
    , [false, false, false, false, false, false, false, false, false]
    , [false, false, false, false, false, false, false, false, false]
    , [false, false, false, false, false, false, false, false, false]
    , [false, false, false, false, false, false, false, false, false]
    , [false, false, false, false, false, false, false, false, false]
    , [false, false, false, false, false, false, false, false, false]
    , [false, false, false, false, false, false, false, false, false]
    , [false, false, false, false, false, false, false, false, false]
  ];

  posList: Collections.Dictionary<number, number>[];

  closeResult: string;

  retList = []; //存放可能的结果

  constructor(private modalService: NgbModal
    , private creator: JgongCreatorService
    , private dcopy: DeepcopyService
  ) {

    this.reset();
    this.setCellNumber(0,0,5);
    this.setCellNumber(0,1,7);
    this.setCellNumber(0,3,1);
    this.setCellNumber(0,4,2);
    this.setCellNumber(2,2,6);
    this.setCellNumber(2,3,7);
    this.setCellNumber(2,7,8);
    this.setCellNumber(3,0,3);
    this.setCellNumber(3,2,4);
    this.setCellNumber(3,5,9);
    this.setCellNumber(3,7,7);
    this.setCellNumber(4,1,2);
    this.setCellNumber(4,4,7);
    this.setCellNumber(4,7,5);
    this.setCellNumber(5,1,1);
    this.setCellNumber(5,3,3);
    this.setCellNumber(5,6,9);
    this.setCellNumber(5,8,2);
    this.setCellNumber(6,1,8);
    this.setCellNumber(6,5,2);
    this.setCellNumber(6,6,1);
    this.setCellNumber(8,4,5);
    this.setCellNumber(8,5,4);
    this.setCellNumber(8,7,6);
    this.setCellNumber(8,8,3);
  }


  public reset() {
    for (var i = 0; i < 9; i++) {
      for (var j = 0; j < 9; j++) {
        this.jgData[i][j] = null;
        this.givenCell[i][j] = false;
      }
    }
  }

  public setCellClass(r, c) {
    let classes = {
      jgcell: true,
      givenCell: this.givenCell[r][c]
    }
    return classes;
  }

  private getDismissReason(reason: any): string {
    if (reason === ModalDismissReasons.ESC) {
      return 'by pressing ESC';
    } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
      return 'by clicking on a backdrop';
    } else {
      return `with: ${reason}`;
    }
  }

  private setCellNumber(r, c, val){
    if (val > 0 && val < 9) {
      this.givenCell[r][c] = true;
      this.jgData[r][c] = val;
    }
    else{
      this.givenCell[r][c] = false;
      this.jgData[r][c] = null;
    }

  }

  openEditer(r: number, c: number) {
    const modalRef = this.modalService.open(ModelInputComponent);
    modalRef.result.then((result) => {
      this.closeResult = `填入: ${result}`;
      this.setCellNumber(r, c, result);
    }, (reason) => {
      this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
    });
  }

  public editNumber(r: number, c: number) {
    this.openEditer(r, c);

  }

  public editNumber2(r: number, c: number, d: any) {
    alert(d.class);
    // this.openEditer(r, c);
  }

  /**
   * 记录已经填入数字的位置和值
   */
  protected commitPosMap() {
    this.posList = [];
    for (var i = 0; i < 9; i++) {
      let posMap = new Collections.Dictionary<number, number>();
      this.posList.push(posMap);
      for (var j = 0; j < 9; j++) {
        let val: number = this.jgData[i][j];
        if (val > 0 && val < 9) {
          posMap.setValue(j, val);
        }
      }
    }

  }

  /**
   * 记录每列已经被用过的数字而不能在生成新序列的时候不能使用
   */
  protected commitRidMap(row: number, data: number[][]): Collections.Dictionary<number, number[]> {
    let ridMap: Collections.Dictionary<number, number[]>;
    ridMap = new Collections.Dictionary<number, number[]>();
    let ridList: number[];
    let val: number;
    for (var i = 0; i < 9; i++) {
      ridList = [];
      for (var j = 0; j < 9; j++) {
        if (j == row) {
          continue;
        }
        val = data[j][i];
        if (val > 0 && val < 10) {
          ridList.push(val);
        }
      }
      ridMap.setValue(i, ridList);

    }

    // ---------------

    let up = Math.floor(row / 3) * 3;
    let down = up + 3;

    for (var i = up; i < down; i++) {
      if (i == row) {
        continue;
      }
      for (var c = 0; c < 9; c++) {
        let cl: number = Math.floor(c / 3) * 3;
        let ch: number = cl + 3;
        for (var j = cl; j < ch; j++) {
          val = data[i][j];
          if (val < 1 || val > 9) {
            continue;
          }
          if (ridMap.getValue(c).indexOf(val) < 0) {
            ridMap.getValue(c).push(val);
          }
        }
      }


    }

    return ridMap;

  }

  public process() {
    this.retList = [];
    this.commitPosMap();
    let data: number[][] = this.dcopy.deepClone(this.jgData);
    this.dealLine(0, data);
    this.closeResult = '总共有 ' + this.retList.length + ' 种可能';
    console.log('total:' + this.retList.length);
    if (this.retList.length > 0) {
      this.jgData = this.dcopy.deepClone(this.retList[0]);
    }
  }

  
  private dealLine(row: number, data: number[][]) {
    let posMap: Collections.Dictionary<number, number>;
    posMap = this.posList[row];

    let ridMap: Collections.Dictionary<number, number[]>;
    ridMap = this.commitRidMap(row, data);

    this.creator.doCreate(ridMap, posMap);
    let len = this.creator.serialization.length;
    if (len <= 0) {
      return;
    }
    let seq = this.creator.serialization.slice(0);
    for (var inx = 0; inx < len; inx++) {
      let s = seq[inx];
      for (var i = 0; i < 9; i++) {
        data[row][i] = s[i];
      }
      console.log(row + ' ' + inx);
      if (row === 8) {
        this.retList.push(data);
        continue;
      }
      let nextData = this.dcopy.deepClone(data);
      let nextRow = row + 1;

      this.dealLine(nextRow, nextData);
    }

  }


}



